
function hook_encrypt()
{
    Java.perform(function () {
        var secretKeySpec = Java.use('javax.crypto.spec.SecretKeySpec');
        secretKeySpec.$init.overload('[B','java.lang.String').implementation = function (a,b) {
            showStacks();
            var result = this.$init(a, b);
            send("======================================");
            send("算法名：" + b + "|Dec密钥:" + bytesToString(a));
            send("算法名：" + b + "|Hex密钥:" + bytesToHex(a));
            return result;
        }
        var mac = Java.use('javax.crypto.Mac');
        mac.getInstance.overload('java.lang.String').implementation = function (a) {
            showStacks();
            var result = this.getInstance(a);
            send("======================================");
            send("算法名：" + a);
            return result;
        }
        mac.update.overload('[B').implementation = function (a) {
            showStacks();
            this.update(a);
            send("======================================");
            send("update:" + bytesToString(a))
        }
        mac.update.overload('[B','int','int').implementation = function (a,b,c) {
            showStacks();
            this.update(a,b,c)
            send("======================================");
            send("update:" + bytesToString(a) + "|" + b + "|" + c);
        }
        mac.doFinal.overload().implementation = function () {
            showStacks();
            var result = this.doFinal();
            send("======================================");
            send("doFinal结果:" + bytesToHex(result));
            send("doFinal结果:" + bytesToBase64(result));
            return result;
        }
        mac.doFinal.overload('[B').implementation = function (a) {
            showStacks();
            var result = this.doFinal(a);
            send("======================================");
            send("doFinal参数:" + bytesToString(a));
            send("doFinal结果:" + bytesToHex(result));
            send("doFinal结果:" + bytesToBase64(result));
            return result;
        }
            var md = Java.use('java.security.MessageDigest');
        md.getInstance.overload('java.lang.String','java.lang.String').implementation = function (a,b) {
            showStacks();
            send("======================================");
            send("算法名：" + a);
            return this.getInstance(a, b);
        }
        md.getInstance.overload('java.lang.String').implementation = function (a) {
            showStacks();
            send("======================================");
            send("算法名：" + a);
            return this.getInstance(a);
        }
        md.update.overload('[B').implementation = function (a) {
            showStacks();
            send("======================================");
            send("update:" + bytesToString(a))
            return this.update(a);
        }
        md.update.overload('[B','int','int').implementation = function (a,b,c) {
            showStacks();
            send("======================================");
            send("update:" + bytesToString(a) + "|" + b + "|" + c);
            return this.update(a,b,c);
        }
        md.digest.overload().implementation = function () {
            showStacks();
            send("======================================");
            var result = this.digest();
            send("digest结果:" + bytesToHex(result));
            send("digest结果:" + bytesToBase64(result));
            return result;
        }
        md.digest.overload('[B').implementation = function (a) {
            showStacks();
            send("======================================");
            send("digest参数:" + bytesToString(a));
            var result = this.digest(a);
            send("digest结果:" + bytesToHex(result));
            send("digest结果:" + bytesToBase64(result));
            return result;
        }
            var ivParameterSpec = Java.use('javax.crypto.spec.IvParameterSpec');
        ivParameterSpec.$init.overload('[B').implementation = function (a) {
            showStacks();
            var result = this.$init(a);
            send("======================================");
            send("iv向量:" + bytesToString(a));
            send("iv向量:" + bytesToHex(a));
            return result;
        }
        var cipher = Java.use('javax.crypto.Cipher');
        cipher.getInstance.overload('java.lang.String').implementation = function (a) {
            showStacks();
            var result = this.getInstance(a);
            send("======================================");
            send("模式填充:" + a);
            return result;
        }
        cipher.update.overload('[B').implementation = function (a) {
            showStacks();
            var result = this.update(a);
            send("======================================");
            send("update:" + bytesToString(a));
            return result;
        }
        cipher.update.overload('[B','int','int').implementation = function (a,b,c) {
            showStacks();
            var result = this.update(a,b,c);
            send("======================================");
            send("update:" + bytesToString(a) + "|" + b + "|" + c);
            return result;
        }
        cipher.doFinal.overload().implementation = function () {
            showStacks();
            var result = this.doFinal();
            send("======================================");
            send("doFinal结果:" + bytesToHex(result));
            send("doFinal结果:" + bytesToBase64(result));
            return result;
        }
        cipher.doFinal.overload('[B').implementation = function (a) {
            showStacks();
            var result = this.doFinal(a);
            send("======================================");
            send("doFinal参数:" + bytesToString(a));
            send("doFinal结果:" + bytesToHex(result));
            send("doFinal结果:" + bytesToBase64(result));
            return result;
        }
        var x509EncodedKeySpec = Java.use('java.security.spec.X509EncodedKeySpec');
        x509EncodedKeySpec.$init.overload('[B').implementation = function (a) {
            showStacks();
            var result = this.$init(a);
            send("======================================");
            send("RSA密钥:" + bytesToBase64(a));
            return result;
        }
        var rSAPublicKeySpec = Java.use('java.security.spec.RSAPublicKeySpec');
        rSAPublicKeySpec.$init.overload('java.math.BigInteger','java.math.BigInteger').implementation = function (a,b) {
            showStacks();
            var result = this.$init(a,b);
            send("======================================");
            //send("RSA密钥:" + bytesToBase64(a));
            send("RSA密钥N:" + a.toString(16));
            send("RSA密钥E:" + b.toString(16));
            return result;
        }
    });
}

function hexToBytes(hex) {
    for (var bytes = [], c = 0; c < hex.length; c += 2)
    bytes.push(parseInt(hex.substr(c, 2), 16));
    return bytes;
}

function stringToHex(str)
{
    return str.split("").map(function(c) {
        return ("0" + c.charCodeAt(0).toString(16)).slice(-2);
    }).join("");
}

function hexToString(hexStr)
{
    var hex = hexStr.toString();
    var str = '';
    for (var i = 0; i < hex.length; i += 2)
        str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
    return str;
}

function bytesToHex(bytes)
{
    for (var hex = [], i = 0; i < bytes.length; i++)
    {
        hex.push((bytes[i] >>> 4).toString(16));
        hex.push((bytes[i] & 0xF).toString(16));
    }
    return hex.join("");
}

function base64ArrayBuffer(arrayBuffer)
{
  var base64    = ''
  var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

  var bytes         = new Uint8Array(arrayBuffer)
  var byteLength    = bytes.byteLength
  var byteRemainder = byteLength % 3
  var mainLength    = byteLength - byteRemainder

  var a, b, c, d
  var chunk

  // Main loop deals with bytes in chunks of 3
  for (var i = 0; i < mainLength; i = i + 3) {
    // Combine the three bytes into a single integer
    chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]

    // Use bitmasks to extract 6-bit segments from the triplet
    a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
    b = (chunk & 258048)   >> 12 // 258048   = (2^6 - 1) << 12
    c = (chunk & 4032)     >>  6 // 4032     = (2^6 - 1) << 6
    d = chunk & 63               // 63       = 2^6 - 1

    // Convert the raw binary segments to the appropriate ASCII encoding
    base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
  }

  // Deal with the remaining bytes and padding
  if (byteRemainder == 1) {
    chunk = bytes[mainLength]

    a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2

    // Set the 4 least significant bits to zero
    b = (chunk & 3)   << 4 // 3   = 2^2 - 1

    base64 += encodings[a] + encodings[b] + '=='
  } else if (byteRemainder == 2) {
    chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]

    a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
    b = (chunk & 1008)  >>  4 // 1008  = (2^6 - 1) << 4

    // Set the 2 least significant bits to zero
    c = (chunk & 15)    <<  2 // 15    = 2^4 - 1

    base64 += encodings[a] + encodings[b] + encodings[c] + '='
  }

  return base64
}

